/** **********************************************************************************
 * @file    8.D.c
 * @mainpage
 * @date    2013-09-29 23:05
 * @author  Alexey Kulikov <alexeyqu@gmail.com>, group 376, DCAM MIPT
 * @version 1.00
 *
 * Computes amount of different numbers with determined sum of digits.
 *
 * @par     The task.
 *          The program calculates the amount of fixed-order numbers with determined sum
 *
 * @note    A global array structure is used here cause it's mentioned in the task.
 *
 * @warning 0 < orders < 10, 0 <= sum <= 90.
**************************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#define DEBUG
#define MAX_ORDERS 11
#define MAX_SUM 92

#ifdef DEBUG
    #define DBG printf ("# "),
    #define ASSERT(cond)                                                              \
    if (!(cond))                                                                      \
    {                                                                                 \
        printf ("Critical failure in assertion '%s'! \nfile %s, line %d \n"           \
                "Now keep calm and EXTERMINATE! EXTERMINATE! EXTERMINATE!!!\n"        \
                , #cond, __FILE__, __LINE__);                                         \
        abort();                                                                      \
    }
#else
    #define DBG if (0)
    #define ASSERT(cond)
#endif

long long int NumbersQuantity[MAX_SUM][MAX_ORDERS] = {0};

/** ********************************************************************************
 * Process_Data - fills the matrix of amounts
************************************************************************************/
void Process_Data();

int main()
{
    DBG printf ("C language test'07. \n");
    DBG printf ("8.D problem. \n");
    DBG printf ("Numbers with determined sum of digits. \n");
    DBG printf ("Enter number of orders and sum of digits: \n->\n ");

    int orders = 0, sum = 0; //!< Main parametres
    int res_input = 0; //!< value that controls correct input

    res_input = scanf ("%d %d", &sum, &orders);
    ASSERT (res_input);
    ASSERT (sum >= 0); ASSERT (sum <= 90);
    ASSERT (orders > 0); ASSERT (orders <= 10);

    Process_Data();

    DBG printf ("Result: \n->");

    printf ("%lld", NumbersQuantity[sum][orders]);

    return 0;
}\

void Process_Data()
{
    int i = 0, j = 0, k = 0; //!< Counters

    for (i = 0; i < MAX_SUM; i++)
    {
        NumbersQuantity[i][0] = 0;
        if (i <= 9) NumbersQuantity[i][1] = 1;
        else NumbersQuantity[i][1] = 0;
    }

    for (j = 1; j < MAX_ORDERS; j++)
    {
        NumbersQuantity[0][j] = 1;
    }

    for (j = 2; j < MAX_ORDERS; j++)
    {
        for (i = 1; i < MAX_SUM; i++)
        {
            for (k = i; k >= i - 9 && k >= 0; k--)
            {
                NumbersQuantity[i][j] += NumbersQuantity[k][j - 1];
                ASSERT (NumbersQuantity[i][j] < LONG_MAX);
            }
        }
    }
}
